#!/usr/bin/env python3
"""
AI Historical Simulation Platform - Main Application

This is the main entry point for the AI Historical Simulation Platform.
It provides multiple interfaces for interacting with historical figures:

- Interactive chat mode
- Demo mode with pre-configured scenarios  
- Web interface for browser-based interaction
- API server for programmatic access
- Command-line interface for all operations

Run directly with: python app.py

让有趣的灵魂跨越时空在当下聚首
Let fascinating souls gather across time in the present
"""

import asyncio
import argparse
import sys
import os
import logging
from pathlib import Path
from typing import Optional, Dict, Any, List
import json
import time

# Add src directory to path
sys.path.insert(0, str(Path(__file__).parent / "src"))

try:
    from src.platform.historical_simulation_platform import HistoricalSimulationPlatform, managed_platform
    from src.platform.performance_monitor import PerformanceMonitor, managed_performance_monitor
    from src.config.settings import Config, get_default_platform_config
    from src.hdc.core import HDCOperations
    from src.personality.models import BigFiveTraits, CulturalDimensions
    from src.personality.encoder import PersonalityEncoder
except ImportError as e:
    print(f"❌ Import error: {e}")
    print("Please ensure all dependencies are installed and the src directory structure is correct.")
    sys.exit(1)


class AIHistoricalSimulationApp:
    """
    Main application class for the AI Historical Simulation Platform.
    
    This class provides a unified interface for all platform functionality
    including interactive chat, demo modes, web interface, and API access.
    """
    
    def __init__(self, config: Optional[Config] = None):
        """Initialize the application."""
        self.config = config or get_default_platform_config()
        self.setup_logging()
        
        # Platform components (will be initialized when needed)
        self.platform = None
        self.performance_monitor = None
        self.is_initialized = False
        
        # Historical figures data
        self.historical_figures = {}
        self.load_historical_figures_data()
        
        logger.info("AI Historical Simulation App initialized")
    
    def setup_logging(self):
        """Setup logging configuration."""
        logging.basicConfig(
            level=getattr(logging, self.config.log_level),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            handlers=[
                logging.StreamHandler(),
                logging.FileHandler('historical_simulation.log')
            ]
        )
        
        global logger
        logger = logging.getLogger(__name__)
    
    def load_historical_figures_data(self):
        """Load historical figures data."""
        # Pre-configured historical figures with basic data
        self.historical_figures = {
            "Napoleon Bonaparte": {
                "name": "Napoleon Bonaparte",
                "historical_period": "1769-1821",
                "biography": {
                    "birth_year": 1769,
                    "death_year": 1821,
                    "nationality": "French",
                    "occupation": "Emperor, Military Commander",
                    "key_achievements": [
                        "Emperor of France",
                        "Napoleonic Code",
                        "Military conquests across Europe",
                        "Administrative and legal reforms"
                    ],
                    "key_events": [
                        "Born in Corsica",
                        "French Revolution participation",
                        "Coup of 18 Brumaire",
                        "Coronation as Emperor",
                        "Battle of Austerlitz",
                        "Exile to Elba",
                        "Return during Hundred Days",
                        "Battle of Waterloo",
                        "Exile to Saint Helena"
                    ]
                },
                "traits": {
                    "openness": 0.8,
                    "conscientiousness": 0.9,
                    "extraversion": 0.9,
                    "agreeableness": 0.3,
                    "neuroticism": 0.4
                },
                "cultural_context": {
                    "language_style": "formal, authoritative",
                    "era_knowledge": "Early 19th century Europe",
                    "cultural_background": "French Revolutionary era",
                    "power_distance": 0.9,
                    "individualism": 0.7,
                    "masculinity": 0.8,
                    "uncertainty_avoidance": 0.6,
                    "long_term_orientation": 0.8,
                    "indulgence": 0.4
                }
            },
            "Albert Einstein": {
                "name": "Albert Einstein",
                "historical_period": "1879-1955",
                "biography": {
                    "birth_year": 1879,
                    "death_year": 1955,
                    "nationality": "German-American",
                    "occupation": "Theoretical Physicist",
                    "key_achievements": [
                        "Theory of Relativity",
                        "Nobel Prize in Physics",
                        "Mass-energy equivalence (E=mc²)",
                        "Photoelectric effect explanation"
                    ],
                    "key_events": [
                        "Born in Germany",
                        "Swiss Patent Office work",
                        "Annus Mirabilis papers",
                        "Nobel Prize awarded",
                        "Immigration to United States",
                        "Manhattan Project involvement",
                        "Advocacy for civil rights"
                    ]
                },
                "traits": {
                    "openness": 0.95,
                    "conscientiousness": 0.8,
                    "extraversion": 0.4,
                    "agreeableness": 0.7,
                    "neuroticism": 0.3
                },
                "cultural_context": {
                    "language_style": "thoughtful, precise",
                    "era_knowledge": "Early-mid 20th century",
                    "cultural_background": "German-Jewish intellectual",
                    "power_distance": 0.3,
                    "individualism": 0.8,
                    "masculinity": 0.4,
                    "uncertainty_avoidance": 0.4,
                    "long_term_orientation": 0.9,
                    "indulgence": 0.6
                }
            },
            "William Shakespeare": {
                "name": "William Shakespeare",
                "historical_period": "1564-1616",
                "biography": {
                    "birth_year": 1564,
                    "death_year": 1616,
                    "nationality": "English",
                    "occupation": "Playwright, Poet, Actor",
                    "key_achievements": [
                        "Hamlet, Romeo and Juliet, Macbeth",
                        "39 plays and 154 sonnets",
                        "Globe Theatre involvement",
                        "English language innovation"
                    ],
                    "key_events": [
                        "Born in Stratford-upon-Avon",
                        "Marriage to Anne Hathaway",
                        "Move to London theater scene",
                        "Lord Chamberlain's Men membership",
                        "Globe Theatre construction",
                        "Royal patronage under King James I"
                    ]
                },
                "traits": {
                    "openness": 0.95,
                    "conscientiousness": 0.7,
                    "extraversion": 0.8,
                    "agreeableness": 0.6,
                    "neuroticism": 0.5
                },
                "cultural_context": {
                    "language_style": "eloquent, poetic, Elizabethan",
                    "era_knowledge": "Elizabethan England",
                    "cultural_background": "English Renaissance",
                    "power_distance": 0.8,
                    "individualism": 0.5,
                    "masculinity": 0.7,
                    "uncertainty_avoidance": 0.6,
                    "long_term_orientation": 0.5,
                    "indulgence": 0.7
                }
            },
            "Leonardo da Vinci": {
                "name": "Leonardo da Vinci",
                "historical_period": "1452-1519",
                "biography": {
                    "birth_year": 1452,
                    "death_year": 1519,
                    "nationality": "Italian",
                    "occupation": "Polymath, Artist, Inventor, Scientist",
                    "key_achievements": [
                        "Mona Lisa and The Last Supper",
                        "Anatomical studies",
                        "Engineering designs",
                        "Scientific observations"
                    ],
                    "key_events": [
                        "Born in Vinci, Italy",
                        "Apprenticeship with Verrocchio",
                        "Milan court artist",
                        "Scientific studies and inventions",
                        "French court patronage"
                    ]
                },
                "traits": {
                    "openness": 1.0,
                    "conscientiousness": 0.6,
                    "extraversion": 0.7,
                    "agreeableness": 0.6,
                    "neuroticism": 0.4
                },
                "cultural_context": {
                    "language_style": "curious, analytical, Renaissance",
                    "era_knowledge": "Italian Renaissance",
                    "cultural_background": "Renaissance humanism",
                    "power_distance": 0.7,
                    "individualism": 0.8,
                    "masculinity": 0.6,
                    "uncertainty_avoidance": 0.3,
                    "long_term_orientation": 0.9,
                    "indulgence": 0.8
                }
            },
            "Marie Curie": {
                "name": "Marie Curie",
                "historical_period": "1867-1934",
                "biography": {
                    "birth_year": 1867,
                    "death_year": 1934,
                    "nationality": "Polish-French",
                    "occupation": "Physicist, Chemist",
                    "key_achievements": [
                        "First woman Nobel Prize winner",
                        "Only person to win Nobel Prizes in two sciences",
                        "Discovery of polonium and radium",
                        "Pioneering research on radioactivity"
                    ],
                    "key_events": [
                        "Born in Warsaw, Poland",
                        "Moved to Paris for education",
                        "Marriage to Pierre Curie",
                        "Discovery of radioactive elements",
                        "First Nobel Prize (Physics)",
                        "Second Nobel Prize (Chemistry)",
                        "Founded Radium Institute"
                    ]
                },
                "traits": {
                    "openness": 0.9,
                    "conscientiousness": 0.95,
                    "extraversion": 0.4,
                    "agreeableness": 0.7,
                    "neuroticism": 0.3
                },
                "cultural_context": {
                    "language_style": "precise, scientific, modest",
                    "era_knowledge": "Late 19th/early 20th century",
                    "cultural_background": "Polish-French scientific community",
                    "power_distance": 0.4,
                    "individualism": 0.6,
                    "masculinity": 0.3,
                    "uncertainty_avoidance": 0.5,
                    "long_term_orientation": 0.9,
                    "indulgence": 0.4
                }
            }
        }
        
        logger.info(f"Loaded {len(self.historical_figures)} historical figures")
    
    async def initialize_platform(self):
        """Initialize the platform components."""
        if self.is_initialized:
            return
        
        print("🚀 Initializing AI Historical Simulation Platform...")
        start_time = time.time()
        
        try:
            # Initialize platform and performance monitor
            async with managed_performance_monitor() as performance_monitor:
                async with managed_platform(
                    hdc_dimension=self.config.hdc.vector_dimension,
                    config=self.config,
                    max_concurrent_sessions=self.config.max_concurrent_sessions
                ) as platform:
                    
                    self.platform = platform
                    self.performance_monitor = performance_monitor
                    
                    # Pre-load historical figures
                    print("📚 Loading historical figures...")
                    await self.load_all_figures()
                    
                    self.is_initialized = True
                    
                    init_time = time.time() - start_time
                    print(f"✅ Platform initialized successfully in {init_time:.2f}s")
                    print(f"📊 Loaded {len(self.historical_figures)} historical figures")
                    print()
                    
                    # Keep platform running for the session
                    yield platform, performance_monitor
                    
        except Exception as e:
            print(f"❌ Failed to initialize platform: {e}")
            logger.exception("Platform initialization failed")
            raise
    
    async def load_all_figures(self):
        """Load all historical figures into the platform."""
        for figure_name, figure_data in self.historical_figures.items():
            try:
                await self.platform.load_historical_figure(figure_name)
                print(f"  ✓ Loaded {figure_name}")
            except Exception as e:
                print(f"  ⚠️  Failed to load {figure_name}: {e}")
                logger.warning(f"Failed to load {figure_name}: {e}")
    
    async def interactive_chat(self):
        """Interactive chat mode with historical figures."""
        print("🎭 Welcome to Interactive Chat Mode!")
        print("Chat with historical figures from across time.")
        print("Available figures:")
        
        for i, name in enumerate(self.historical_figures.keys(), 1):
            period = self.historical_figures[name]["historical_period"]
            print(f"  {i}. {name} ({period})")
        
        print("\nCommands:")
        print("  /list - Show available figures")
        print("  /switch <name> - Switch to a different figure")
        print("  /info - Show current figure information")
        print("  /exit - Exit chat mode")
        print()
        
        # Default to Napoleon
        current_figure = "Napoleon Bonaparte"
        session_id = await self.platform.session_manager.create_session(
            user_id="interactive_user",
            session_metadata={"mode": "interactive_chat"}
        )
        
        print(f"💬 Now chatting with {current_figure}")
        print(f"⏰ From {self.historical_figures[current_figure]['historical_period']}")
        print("=" * 60)
        
        while True:
            try:
                user_input = input(f"\nYou: ").strip()
                
                if not user_input:
                    continue
                
                # Handle commands
                if user_input.startswith('/'):
                    if user_input == '/exit':
                        print("\n👋 Goodbye! Thanks for chatting with history!")
                        break
                    elif user_input == '/list':
                        print("\nAvailable historical figures:")
                        for name in self.historical_figures.keys():
                            period = self.historical_figures[name]["historical_period"]
                            print(f"  - {name} ({period})")
                        continue
                    elif user_input.startswith('/switch '):
                        new_figure = user_input[8:].strip()
                        if new_figure in self.historical_figures:
                            current_figure = new_figure
                            print(f"\n💬 Now chatting with {current_figure}")
                            print(f"⏰ From {self.historical_figures[current_figure]['historical_period']}")
                        else:
                            print(f"❌ Figure '{new_figure}' not available. Use /list to see options.")
                        continue
                    elif user_input == '/info':
                        info = self.historical_figures[current_figure]
                        print(f"\n📖 Information about {current_figure}:")
                        print(f"   Period: {info['historical_period']}")
                        print(f"   Occupation: {info['biography']['occupation']}")
                        print(f"   Key achievements: {', '.join(info['biography']['key_achievements'][:3])}")
                        continue
                    else:
                        print("❓ Unknown command. Type /exit to quit or /list for figures.")
                        continue
                
                # Generate response
                print(f"\n{current_figure}: ", end="", flush=True)
                
                start_time = time.time()
                response = await self.platform.generate_response(
                    session_id=session_id,
                    figure_name=current_figure,
                    user_input=user_input
                )
                response_time = time.time() - start_time
                
                print(response)
                print(f"\n⏱️  Response time: {response_time*1000:.1f}ms")
                
            except KeyboardInterrupt:
                print("\n\n👋 Goodbye! Thanks for chatting with history!")
                break
            except Exception as e:
                print(f"\n❌ Error: {e}")
                logger.exception("Chat error")
    
    async def demo_mode(self):
        """Demo mode with pre-configured scenarios."""
        print("🎬 Welcome to Demo Mode!")
        print("Experience pre-configured scenarios with historical figures.")
        print()
        
        # Demo scenarios
        scenarios = [
            {
                "name": "Leadership Discussion",
                "description": "Napoleon and Einstein discuss leadership styles",
                "participants": ["Napoleon Bonaparte", "Albert Einstein"],
                "topic": "What makes an effective leader in times of change?",
                "rounds": 2
            },
            {
                "name": "Creative Inspiration",
                "description": "Shakespeare and Leonardo discuss the creative process",
                "participants": ["William Shakespeare", "Leonardo da Vinci"],
                "topic": "Where does creative inspiration come from?",
                "rounds": 2
            },
            {
                "name": "Scientific Revolution",
                "description": "Einstein and Marie Curie on scientific discovery",
                "participants": ["Albert Einstein", "Marie Curie"],
                "topic": "How do breakthrough scientific discoveries happen?",
                "rounds": 2
            }
        ]
        
        print("Available demo scenarios:")
        for i, scenario in enumerate(scenarios, 1):
            print(f"  {i}. {scenario['name']}: {scenario['description']}")
        
        while True:
            try:
                choice = input("\nSelect scenario (1-3) or 'q' to quit: ").strip()
                
                if choice.lower() == 'q':
                    break
                
                if choice.isdigit() and 1 <= int(choice) <= len(scenarios):
                    scenario = scenarios[int(choice) - 1]
                    await self.run_demo_scenario(scenario)
                else:
                    print("❌ Invalid choice. Please select 1-3 or 'q'.")
                    
            except KeyboardInterrupt:
                break
            except Exception as e:
                print(f"❌ Error: {e}")
                logger.exception("Demo error")
        
        print("\n👋 Demo mode ended!")
    
    async def run_demo_scenario(self, scenario: Dict[str, Any]):
        """Run a specific demo scenario."""
        print(f"\n🎭 Starting: {scenario['name']}")
        print(f"📝 {scenario['description']}")
        print(f"👥 Participants: {', '.join(scenario['participants'])}")
        print(f"🎯 Topic: {scenario['topic']}")
        print("=" * 80)
        
        session_id = await self.platform.session_manager.create_session(
            user_id="demo_user",
            session_metadata={"mode": "demo", "scenario": scenario['name']}
        )
        
        try:
            conversation = await self.platform.create_cross_temporal_conversation(
                session_id=session_id,
                figure_names=scenario['participants'],
                topic=scenario['topic'],
                rounds=scenario['rounds']
            )
            
            print("\n📜 Conversation Transcript:")
            print("-" * 40)
            
            for exchange in conversation:
                figure = exchange['figure']
                response = exchange['response']
                round_num = exchange['round']
                period = self.historical_figures[figure]['historical_period']
                
                print(f"\n🗣️  {figure} ({period}) - Round {round_num}:")
                print(f"💬 {response}")
            
            print("\n" + "=" * 80)
            print("🎉 Scenario completed successfully!")
            
            # Ask if user wants to continue the conversation
            continue_choice = input("\nWould you like to ask a follow-up question? (y/n): ").strip().lower()
            
            if continue_choice == 'y':
                question = input("Your question: ").strip()
                if question:
                    print(f"\n🤔 You ask: {question}")
                    print("-" * 40)
                    
                    for figure in scenario['participants']:
                        response = await self.platform.generate_response(
                            session_id=session_id,
                            figure_name=figure,
                            user_input=question
                        )
                        period = self.historical_figures[figure]['historical_period']
                        print(f"\n🗣️  {figure} ({period}):")
                        print(f"💬 {response}")
                    
        except Exception as e:
            print(f"❌ Scenario failed: {e}")
            logger.exception("Demo scenario error")
    
    async def show_platform_status(self):
        """Show platform status and statistics."""
        print("📊 Platform Status")
        print("=" * 50)
        
        try:
            # Get platform health
            health = await self.platform.get_platform_health()
            print(f"🟢 Platform Health: {'Healthy' if health.is_healthy else 'Warning'}")
            print(f"⏰ Uptime: {health.uptime_seconds:.1f} seconds")
            print(f"💾 Memory Usage: {health.memory_usage_mb:.1f} MB")
            print(f"👥 Active Sessions: {health.active_sessions}")
            print(f"📚 Loaded Figures: {health.loaded_figures}")
            print(f"⚡ Avg Response Time: {health.avg_response_time_ms:.1f}ms")
            print(f"🎯 Error Rate: {health.error_rate:.1%}")
            
            # Get system metrics
            metrics = await self.platform.get_system_metrics()
            print(f"\n📈 System Metrics:")
            print(f"   Total Conversations: {metrics['figures']['total_conversations']}")
            print(f"   Average Quality: {metrics['figures']['avg_quality']:.3f}")
            print(f"   HDC Dimension: {metrics['system']['hdc_dimension']}")
            
            # Performance metrics
            if self.performance_monitor:
                current_metrics = await self.performance_monitor.get_current_metrics()
                if current_metrics.get('response_times'):
                    rt = current_metrics['response_times']
                    print(f"\n⚡ Performance:")
                    print(f"   Response Time Avg: {rt.get('avg', 0):.1f}ms")
                    print(f"   Total Requests: {rt.get('count', 0)}")
                
        except Exception as e:
            print(f"❌ Error getting status: {e}")
            logger.exception("Status error")
    
    def show_help(self):
        """Show help information."""
        print("🎭 AI Historical Simulation Platform")
        print("让有趣的灵魂跨越时空在当下聚首")
        print("Let fascinating souls gather across time in the present")
        print()
        print("Available modes:")
        print("  chat      - Interactive chat with historical figures")
        print("  demo      - Run pre-configured demo scenarios") 
        print("  status    - Show platform status and statistics")
        print("  figures   - List available historical figures")
        print("  help      - Show this help message")
        print()
        print("Examples:")
        print("  python app.py chat")
        print("  python app.py demo")
        print("  python app.py status")
        print()
    
    def list_figures(self):
        """List available historical figures."""
        print("📚 Available Historical Figures")
        print("=" * 50)
        
        for name, data in self.historical_figures.items():
            period = data['historical_period']
            occupation = data['biography']['occupation']
            achievements = data['biography']['key_achievements'][:2]
            
            print(f"\n🎭 {name}")
            print(f"   Period: {period}")
            print(f"   Role: {occupation}")
            print(f"   Known for: {', '.join(achievements)}")
    
    async def run_cli(self, args):
        """Run the command-line interface."""
        if args.mode == 'help' or not args.mode:
            self.show_help()
            return
        
        if args.mode == 'figures':
            self.list_figures()
            return
        
        # For modes that need the platform, initialize it
        if args.mode in ['chat', 'demo', 'status']:
            async with self.initialize_platform() as (platform, performance_monitor):
                if args.mode == 'chat':
                    await self.interactive_chat()
                elif args.mode == 'demo':
                    await self.demo_mode()
                elif args.mode == 'status':
                    await self.show_platform_status()
        else:
            print(f"❌ Unknown mode: {args.mode}")
            self.show_help()


async def main():
    """Main application entry point."""
    parser = argparse.ArgumentParser(
        description="AI Historical Simulation Platform - Chat with historical figures across time"
    )
    parser.add_argument(
        'mode', 
        nargs='?',
        choices=['chat', 'demo', 'status', 'figures', 'help'],
        default='help',
        help='Application mode'
    )
    parser.add_argument(
        '--config',
        type=str,
        help='Path to configuration file'
    )
    parser.add_argument(
        '--debug',
        action='store_true',
        help='Enable debug mode'
    )
    
    args = parser.parse_args()
    
    # Load config
    if args.config:
        try:
            with open(args.config, 'r') as f:
                config_dict = json.load(f)
            config = Config.from_dict(config_dict)
        except Exception as e:
            print(f"❌ Failed to load config from {args.config}: {e}")
            sys.exit(1)
    else:
        config = get_default_platform_config()
    
    if args.debug:
        config.debug = True
        config.log_level = "DEBUG"
    
    # Create and run app
    try:
        app = AIHistoricalSimulationApp(config)
        await app.run_cli(args)
    except KeyboardInterrupt:
        print("\n👋 Goodbye!")
    except Exception as e:
        print(f"❌ Application error: {e}")
        if config.debug:
            import traceback
            traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n👋 Goodbye!")
    except Exception as e:
        print(f"❌ Fatal error: {e}")
        sys.exit(1)